EAX     = 0x00  # 相对于栈指针的偏移
EBX     = 0x04
ECX     = 0x08
EDX     = 0x0C
FS      = 0x10
ES      = 0x14
DS      = 0x18
EIP     = 0x1C
CS      = 0x20
EFLAGS  = 0x24
OLDESP  = 0x28
OLDSS   = 0x2C

state   = 0     # 相对于任务结构体的偏移
counter = 4

nr_system_calls = 72

.globl system_call, sys_fork, timer_interrupt

.align 4
bad_sys_call:
    movl $-1, %eax
    iret
.align 4
reschedule:
    pushl $ret_from_sys_call
    jmp schedule
.align 4
system_call:
    cmpl $nr_system_calls - 1, %eax
    ja bad_sys_call
    push %ds
    push %es
    push %fs
    pushl %edx
    pushl %ecx        # 将edx，ecx和ebx入栈作为参数
    pushl %ebx
    movl $0x10, %edx        # ds和es用于访问系统数据
    mov %dx, %ds
    mov %dx, %es
    movl $0x17, %edx        # fs用于访问用户数据
    mov %dx, %fs
    call sys_call_table(, %eax, 4)
    pushl %eax
    movl current, %eax
    cmpl $0, state(%eax)        # 状态
    jne reschedule
    cmpl $0, counter(%eax)      # 时间片
    je reschedule
ret_from_sys_call:
3:  popl %eax
    popl %ebx
    popl %ecx
    popl %edx
    pop %fs
    pop %es
    pop %ds
    iret

.align 4
timer_interrupt:
    push %ds
    push %es
    push %fs
    pushl %edx
    pushl %ecx
    pushl %ebx
    pushl %eax
    movl $0x10, %eax        # ds和es用于访问系统数据
    mov %ax, %ds
    mov %ax, %es
    movl $0x17, %eax        # fs用于访问用户数据
    mov %ax, %fs
    incl jiffies
    movb $0x20, %al
    outb %al, $0x20
    movl CS(%esp), %eax
    andl $3, %eax           # eax作为特权级别
    pushl %eax
    call do_timer
    addl $4, %esp
    jmp ret_from_sys_call

.align 4
sys_fork:
    call find_empty_process
    testl %eax, %eax
    js 1f
    push %gs
    pushl %esi
    pushl %edi
    pushl %ebp
    pushl %eax
    call copy_process
    addl $20, %esp
1:  ret
